import * as THREE from 'three';
import { OrbitControls } from 'OrbitControls';
import Stats from 'Stats';
import { GUI } from 'GUI';

// 基本概念：场景Scene、相机Camera、渲染器Renderer

// // 定义相机渲染输出的画布尺寸
// const width = 800;
// const height = 500;

// 1、创建3D场景对象Scene
const scene = new THREE.Scene();

// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 1, 100);

// 实例化 WebGL 渲染器
const renderer = new THREE.WebGLRenderer({
  // 锯齿模糊，开启后几何体形状过渡平滑
  antialias: true,
});
// 锯齿
// renderer.antialias = true;
// 获取你屏幕对应的设备像素比.devicePixelRatio告诉threejs,以免渲染模糊问题，是1 的话设不设置都一样
// renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0xcccccc, 1); //设置背景颜色
// 设置 threejs 渲染区域
renderer.setSize(window.innerWidth, window.innerHeight);

// 添加到 dom， renderer.domElement 实际上就是画布 canvas
const container = document.querySelector('#webgl');
container.appendChild(renderer.domElement);

// 创建一个几何对象 Geometry
const boxGeometry = new THREE.BoxGeometry(5, 5, 5);
// 创建一个材质对象 Material
const material = new THREE.MeshPhongMaterial({
  color: 0xff3fff,
  side: THREE.DoubleSide, // 双面可见，默认正面可见 THREE.FrontSide
  // wireframe: true, // 线框
  // transparent: true, // 开启透明
  // opacity: 0.4, // 透明度
});
// 创建网格模型对象 传入 几何体geometry、材质material
const mesh = new THREE.Mesh(boxGeometry, material);
// 网格模型位置，默认原点
mesh.position.set(0, 20, 0);

// 相机位置
camera.position.set(20, 30, 40);
// 相机观察位置
camera.lookAt(mesh.position);

// 添加网格模型到场景
scene.add(mesh);

// 辅助观察坐标系
const axesHelper = new THREE.AxesHelper(50);
scene.add(axesHelper);

// 点光源 添加光源
const pointLight = new THREE.PointLight(0xffffff, 1.0);
pointLight.position.set(10, 30, 10);
scene.add(pointLight);

// 相机控制器
const controls = new OrbitControls(camera, renderer.domElement);
// // 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
// controls.addEventListener('change', function () {
//   renderer.render(scene, camera); //执行渲染操作
//   // 浏览器控制台查看相机位置变化
//   // console.log('camera.position',camera.position);
// });//监听鼠标、键盘事件

// //环境光:没有特定方向，整体改变场景的光照明暗
// const ambientLight = new THREE.AmbientLight(0xffff00, 1);
// ambientLight.position.set(10, 20, 0);
// scene.add(ambientLight);

// 光源辅助观察
const pointLightHelper = new THREE.PointLightHelper(pointLight, 2);
scene.add(pointLightHelper);

// 窗口大小
window.onresize = function() {
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
}

// 创建 stats 对象
const stats = new Stats();
document.body.appendChild(stats.domElement);

const getRandomColor = () => {
  let hex = Math.floor(Math.random() * 16777216).toString(16);
  while(hex.length < 6) {
    hex = '0' + hex;
  }
  return '#' + hex;
}

// 随机创建大量的模型,测试渲染性能，调整 num 值查看页面帧率变化
const num = 10; //控制长方体模型数量
for (let i = 0; i < num; i++) {
  for (let j = 0; j < num; j++) {
    for (let k = 0; k < num; k++) {
      const geometry = new THREE.BoxGeometry(1, 1, 1);
      const material = new THREE.MeshLambertMaterial({
        color: getRandomColor(),
        transparent: true,
        opacity: 0.8,
      });
      const mesh = new THREE.Mesh(geometry, material);
      // 随机生成长方体xyz坐标
      const x = i * 2
      const y = k * 2
      const z = j * 2
      mesh.position.set(x, y, z)
      scene.add(mesh); // 模型对象插入场景中
    }
  }
}

// 球体 几何体
const sphereGeometry = new THREE.SphereGeometry(2);
// 高光网格材质
// 模拟镜面反射，产生一个高光效果
const phongMaterial = new THREE.MeshPhongMaterial({
  color: 0xF80888,
  shininess: 40, //高光部分的亮度，默认30
  specular: 0xFFFFFF, //高光部分的颜色
});
// 网格模型
const mesh2 = new THREE.Mesh(sphereGeometry, phongMaterial);
// 网格模型位置，默认原点
mesh2.position.set(10, 25, 10);
scene.add(mesh2);

// 创建一个GUI
const gui = new GUI();
//改变交互界面style属性
gui.domElement.style.right = '0px';
gui.domElement.style.width = '300px';
// 通过GUI改变对象属性，其余参数为数值
// 最外层菜单
gui.add(pointLight, 'intensity', 0, 2.0).name('环境光强度');
// gui.add(mesh.position, 'y', 0, 30).step(2).name('y轴');
// // .add 的其余参数为对象 、 数组，gui界面为下拉选择
// gui.add(material, 'transparent', { 开: true, 关: false}).name('开启透明');
// gui.add(material, 'opacity', [0.2, 0.4, 0.6, 0.8, 1]).name('透明度');
// // .add 的其余参数为 布尔值
// const isMove = { bool: true };
// gui.add(isMove, 'bool').name('矩形动画');
// // 颜色
// gui.addColor(phongMaterial, 'color').name('球体颜色').onChange(function(color) {
//   // renderer.setClearColor(color, 1);
// });

// gui 创建子菜单
const boxFolder = gui.addFolder('矩形');
boxFolder.close(); // 折叠
boxFolder.add(mesh.position, 'y', 0, 30).step(2).name('y轴');
const isMove = { bool: true };
boxFolder.add(isMove, 'bool').name('矩形动画');
// 嵌套子菜单
const transparentFolder = boxFolder.addFolder('透明');
transparentFolder.add(material, 'transparent', { 开: true, 关: false}).name('开启透明');
transparentFolder.add(material, 'opacity', [0.2, 0.4, 0.6, 0.8, 1]).name('透明度');

// 创建子菜单
const sphereFolder = gui.addFolder('球体');
// 球体颜色
sphereFolder.addColor(phongMaterial, 'color').name('球体颜色').onChange(function(color) {
  // renderer.setClearColor(color, 1);
});

// 使用 requestAnimationFrame 渲染
const render = () => {
  
  // 更新
  stats.update();

  // mesh是否运动
  if (isMove.bool) {
    mesh.rotation.x += 0.01;
    mesh.rotation.y += 0.01;
  }
  
  // light.rotation.x += 0.1;
  // light.rotation.y += 0.1;
  
  // 渲染
  renderer.render(scene, camera);
  window.requestAnimationFrame(render);
}
render();
